﻿using Microsoft.AspNetCore.Mvc;
using SovaDataService;
using SovaDataService.SoDataServices;
using SovaDataService.SoModels;
using SovaWebService.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;


namespace SovaWebService.Controllers
{
    [Route("api/questions")]
    public class QuestionsController : Controller
    {
        private QuestionDataService _dataService;

        /**
         * Constructor with dependecy injection.
         */
        public QuestionsController(QuestionDataService dataService)
        {
            _dataService = dataService;
        }

        /**
         * Retrieves questions with pageSize and pagination.
         */
        [HttpGet(Name = nameof(GetQuestions))]
        public IActionResult GetQuestions(int page = 0, int pageSize = 10)
        {
            // Retrieving the given page of questions.
            var questions = _dataService.GetAll()
                .Skip(page * pageSize)
                .Take(pageSize);
            int total = _dataService.GetCount();

            // Provide the next and previous page urls.
            var questionsList = new QuestionsListVM()
            {
                PageNumber = page,
                Total = total,
            };

            questionsList.Questions = new List<IQuestionVM>();
            // Populate the question list view model with question view models.
            foreach (var question in questions)
            {
                questionsList.Questions.Add(new QuestionVM()
                {
                    Title = question.Title,
                    Score = question.Score,
                    QuestionUrl = Url.Link(nameof(GetQuestion), new { id = question.Id }),
                    Body = question.Body,
                    AuthorName = question.Author.Name
                });
            }

            // Add pagination properties to the object.
            questionsList += UrlHelper.Pagination(Url, nameof(GetQuestions), page, pageSize, total);
            
            // Return ok with the question list as response.
            return Ok(questionsList);
        }

        /**
         * Retrieves one question by given id.
         */
        [HttpGet("{id}", Name = nameof(GetQuestion))]
        public IActionResult GetQuestion(int id)
        {
            var question = _dataService.GetOne(id);
            if (question == null)
            {
                return NotFound();
            }

            // Get the question details for the question.
            QuestionDetailsVM questionDetailsVM = MapQuestionDetails(question);

            // Return the question details.
            return Ok(questionDetailsVM);
        }

        /**
         * Maps the question to question details.
         */
        private QuestionDetailsVM MapQuestionDetails(Question question)
        {
            // Mapping the fields of the View Model with the ones from the question.
            var questionDetailsVM = new QuestionDetailsVM()
            {
                Id = question.Id.ToString(),
                Title = question.Title,
                Score = question.Score,
                QuestionUrl = Url.Link(nameof(GetQuestion), new { id = question.Id }),
                Body = question.Body,
                AuthorName = question.Author.Name,
                AnswersCount = question.Answers.Count,
                CommentsCount = question.Comments.Count
            };

            if (question.AcceptedAnswer != null)
            {
                // Adding the answer object to the mapped view model.
                questionDetailsVM.AcceptedAnswer = new AnswerVM()
                {
                    Body = question.AcceptedAnswer.Body,
                    Score = question.AcceptedAnswer.Score,
                    AuthorName = question.AcceptedAnswer.Author.Name
                };

                // Adding the comments to the accepted answer.
                questionDetailsVM.AcceptedAnswer.Comments = new List<CommentVM>();
                foreach (var comment in question.AcceptedAnswer.Comments)
                {
                    questionDetailsVM.AcceptedAnswer.Comments.Add(new CommentVM()
                    {
                        Text = comment.Text,
                        Score = comment.Score,
                        //AuthorName = comment.Author.Name
                    });
                }
            }

            if (question.Answers != null && question.Answers.Count > 0)
            {
                // Adding the rest of the answers with their comments
                // to the mapped view model.
                questionDetailsVM.Answers = new List<AnswerVM>();
                foreach (var answer in question.Answers)
                {
                    var answerVM = new AnswerVM();
                    answerVM.Body = answer.Body;
                    answerVM.Score = answer.Score;
                    //answerVM.AuthorName = answer.Author.Name;
                    answerVM.Comments = new List<CommentVM>();

                    foreach (var comment in answer.Comments)
                    {
                        answerVM.Comments.Add(new CommentVM()
                        {
                            Text = comment.Text,
                            Score = comment.Score,
                            //AuthorName = comment.Author.Name
                        });
                    }

                    questionDetailsVM.Answers.Add(answerVM);
                }
            }

            if (question.Comments != null && question.Comments.Count > 0)
            {
                // Add all the comments to the question.
                questionDetailsVM.Comments = new List<CommentVM>();
                foreach (var comment in question.Comments)
                {
                    questionDetailsVM.Comments.Add(new CommentVM()
                    {
                        Text = comment.Text,
                        Score = comment.Score,
                        AuthorName = comment.Author.Name
                    });
                }
            }

            return questionDetailsVM;
        }

    }
}